from odoo import api, models, fields
from odoo.exceptions import ValidationError
from odoo.tools import config
import requests, json
import logging

_logger = logging.getLogger(__name__)


class DingtalkBase(models.AbstractModel):
    _name = 'dingtalk.base'

    def check_params(self):
        """检查获取钉钉凭证应用key"""
        res = True
        config = self.env['dingtalk.config'].search([('company_id', '=', self.env.company.id)])
        if not config or not config.appkey or not config.appsecret:
            res = False
        return res

    def access_token(self):
        """
        获取api凭证
        """
        url = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
        if not self.check_params():
            raise ValidationError('请先配置钉钉应用参数')
        config = self.env['dingtalk.config'].search([('company_id', '=', self.env.company.id)])
        appKey = config.appkey
        appSercet = config.appsecret
        params = json.dumps({"appKey": appKey, "appSecret": appSercet})
        headers = {
            'Content-Type': 'application/json'
        }
        response = requests.request("POST", url, headers=headers, data=params)
        if response.status_code == 200:
            return json.loads(response.text)['accessToken']
        return None

    def user_list(self, dept_ids=[], size=10, cursor=0, access_token=None):
        """获取全量员工信息
        dept_ids：部门钉钉id列表
        size：分页大小
        cursor：分页游标
        access_token：调取钉钉api凭证
        return：员工[{}, {}, {}]
        文档地址：https://open.dingtalk.com/document/orgapp-server/queries-the-complete-information-of-a-department-user
        """
        headers = {
            'Content-Type': 'application/json;charset=utf-8'
        }
        url = "https://oapi.dingtalk.com/topapi/v2/user/list?access_token={}".format(access_token)
        params = json.dumps({"dept_id": dept_ids[0], 'cursor': cursor, 'size': size})
        response = requests.request("POST", url, headers=headers, data=params)
        if response.status_code != 200 or json.loads(response.text)['errmsg'] != 'ok':
            raise ValidationError('获取部门用户失败')
        res = json.loads(response.text)
        if res['result']['has_more']:
            next_cursor = res['result']['next_cursor']
            return res['result']['list'] + self.user_list(dept_ids, 10, next_cursor, access_token)
        else:
            dept_ids.pop(0)
        if not dept_ids:
            return res['result']['list']
        return res['result']['list'] + self.user_list(dept_ids, 10, 0, access_token)

    def department_list(self, dept_ids=[1], access_token=None):
        """获取全量部门信息
        dept_ids: 钉钉部门id列表，默认为[1]获取全量部门id，否则获取获取初始值下全部子部门
        access_token：调取钉钉api凭证
        return: 部门列表 [{}, {}, {}]
        文档地址：https://open.dingtalk.com/document/orgapp-server/obtain-the-department-list-v2
        """
        headers = {
            'Content-Type': 'application/json;charset=utf-8'
        }
        url = "https://oapi.dingtalk.com/topapi/v2/department/listsub?access_token={}".format(access_token)
        params = json.dumps({"dept_id": dept_ids.pop(0)})
        response = requests.request("POST", url, headers=headers, data=params)
        if response.status_code != 200 or json.loads(response.text)['errmsg'] != 'ok':
            _logger.warning('获取部门列表失败： {}'.format(json.loads(response.text)))
            raise ValidationError('获取部门列表失败')
        for res in json.loads(response.text)['result']:
            dept_ids.append(res['dept_id'])
        if not dept_ids:
            return json.loads(response.text)['result']
        return json.loads(response.text)['result'] + self.department_list(dept_ids, access_token)

    def user_access_token(self, code):
        """获取用户token"""
        appkey = config['ding_appkey']
        appsecret = config['ding_appsecret']
        url = """https://api.dingtalk.com/v1.0/oauth2/userAccessToken"""
        headers = {
            'Content-Type': 'application/json;charset=utf-8'
        }
        params = json.dumps({"clientSecret": appsecret,
                             "clientId": appkey,
                             'grantType': 'authorization_code',
                             'code': code})
        response = requests.request("POST", url, headers=headers, data=params)
        if response.status_code != 200 or 'accessToken' not in json.loads(response.text):
            raise ValidationError('换取用户token失败, {}'.format(response.text))
        return json.loads(response.text)['accessToken']

    def contract_user_u(self, authCode):
        """通过用户token获取个人信息"""
        url = """https://api.dingtalk.com/v1.0/contact/users/me"""
        token = self.user_access_token(authCode)
        headers = {
            'Content-Type': 'application/json;charset=utf-8',
            'x-acs-dingtalk-access-token': token
        }
        response = requests.request("GET", url, headers=headers)
        if response.status_code != 200:
            raise ValidationError('用户token获取个人通讯录信息失败, {}'.format(response.text))
        return json.loads(response.text)
